package star.oath.framework.util;

import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.time.temporal.ChronoUnit;
import java.time.temporal.TemporalAdjusters;
import java.util.ArrayList;
import java.util.List;

public class DateRangeUtils {

    // 日期格式常量（以 FORMAT_ 开头）
    public static final DateTimeFormatter FORMAT_ISO_LOCAL_DATE = DateTimeFormatter.ISO_LOCAL_DATE; // yyyy-MM-dd
    public static final DateTimeFormatter FORMAT_BASIC_ISO_DATE = DateTimeFormatter.BASIC_ISO_DATE; // yyyyMMdd
    public static final DateTimeFormatter FORMAT_ISO_DATE_TIME = DateTimeFormatter.ISO_LOCAL_DATE_TIME; // yyyy-MM-ddTHH:mm:ss
    public static final DateTimeFormatter FORMAT_ISO_TIME = DateTimeFormatter.ISO_LOCAL_TIME; // HH:mm:ss
    public static final DateTimeFormatter FORMAT_RFC_1123 = DateTimeFormatter.RFC_1123_DATE_TIME; // EEE, dd MMM yyyy HH:mm:ss z

    // 自定义常用格式
    public static final DateTimeFormatter FORMAT_DATE = DateTimeFormatter.ofPattern("yyyy-MM-dd");
    public static final DateTimeFormatter FORMAT_DATE_TIME = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
    public static final DateTimeFormatter FORMAT_DATE_TIME_MS = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.SSS");
    public static final DateTimeFormatter FORMAT_MONTH_DAY = DateTimeFormatter.ofPattern("MM-dd");
    public static final DateTimeFormatter FORMAT_YEAR_MONTH = DateTimeFormatter.ofPattern("yyyy-MM");
    public static final DateTimeFormatter FORMAT_CHINESE_DATE = DateTimeFormatter.ofPattern("yyyy年MM月dd日");
    public static final DateTimeFormatter FORMAT_CHINESE_DATE_TIME = DateTimeFormatter.ofPattern("yyyy年MM月dd日 HH时mm分ss秒");

    // 其他常用格式（可根据需要扩展）
    public static final DateTimeFormatter FORMAT_USA_DATE = DateTimeFormatter.ofPattern("MM/dd/yyyy");
    public static final DateTimeFormatter FORMAT_USA_DATE_TIME = DateTimeFormatter.ofPattern("MM/dd/yyyy HH:mm:ss");
    public static final DateTimeFormatter FORMAT_EUROPEAN_DATE = DateTimeFormatter.ofPattern("dd/MM/yyyy");

    // 时间范围类型常量
    public static final String RANGE_DAY = "day";
    public static final String RANGE_WEEK = "week";
    public static final String RANGE_WEEK_FULL = "week_full";
    public static final String RANGE_MONTH = "month";
    public static final String RANGE_MONTH_FULL = "month_full";
    public static final String RANGE_SEASON = "season";
    public static final String RANGE_SEASON_FULL = "season_full";
    public static final String RANGE_YEAR = "year";
    public static final String RANGE_YEAR_FULL = "year_full";

    /**
     * 生成指定日期范围内的日期范围列表，支持按不同时间单位分段
     * @param startDate 开始日期字符串
     * @param endDate 结束日期字符串
     * @param format 日期格式（如 FORMAT_XXXX）
     * @param rangeType 时间单位（如 RANGE_XXXX）
     * @return 日期范围列表
     * @throws IllegalArgumentException 如果日期格式无效或日期解析失败
     */
    public static List<DateRange> generateDateRanges(String startDate, String endDate, String format, String rangeType) {
        // 验证输入参数
        if (startDate == null || endDate == null || format == null || rangeType == null) {
            throw new IllegalArgumentException("输入参数不能为 null");
        }

        // 创建日期格式化器
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern(format);

        try {
            // 解析输入的日期字符串
            LocalDate start = LocalDate.parse(startDate, formatter);
            LocalDate end = LocalDate.parse(endDate, formatter);

            // 计算日期范围天数
            long days = ChronoUnit.DAYS.between(start, end);
            if (days < 0) {
                throw new IllegalArgumentException("开始日期不能晚于结束日期");
            }

            // 根据时间单位生成不同的日期范围
            List<DateRange> dateRangeList = new ArrayList<>();

            switch (rangeType) {
                case RANGE_DAY:
                    // 按天分段（原逻辑）
                    for (long i = 0; i <= days; i++) {
                        LocalDate date = start.plusDays(i);
                        String formattedDate = date.format(formatter);
                        dateRangeList.add(new DateRange(formattedDate, formattedDate, 1));
                    }
                    break;
                case RANGE_WEEK:
                    // 按周分段（从startDate开始，每7天一段）
                    LocalDate currentWeekStart = start;
                    while (currentWeekStart.isBefore(end) || currentWeekStart.isEqual(end)) {
                        LocalDate weekEnd = currentWeekStart.plusDays(6); // 下周前一天 = 当前日期+6天
                        if (weekEnd.isAfter(end)) {
                            weekEnd = end;
                        }
                        long daysInWeek = ChronoUnit.DAYS.between(currentWeekStart, weekEnd) + 1;
                        dateRangeList.add(new DateRange(
                                currentWeekStart.format(formatter),
                                weekEnd.format(formatter),
                                (int) daysInWeek
                        ));
                        currentWeekStart = weekEnd.plusDays(1);
                    }
                    break;
                case RANGE_WEEK_FULL:
                    // 按周分段（从周一到周日）
                    LocalDate currentWeekFullStart = start;
                    while (currentWeekFullStart.isBefore(end) || currentWeekFullStart.isEqual(end)) {
                        LocalDate weekEnd = currentWeekFullStart.with(TemporalAdjusters.nextOrSame(java.time.DayOfWeek.SUNDAY));
                        if (weekEnd.isAfter(end)) {
                            weekEnd = end;
                        }
                        long daysInWeek = ChronoUnit.DAYS.between(currentWeekFullStart, weekEnd) + 1;
                        dateRangeList.add(new DateRange(
                                currentWeekFullStart.format(formatter),
                                weekEnd.format(formatter),
                                (int) daysInWeek
                        ));
                        currentWeekFullStart = weekEnd.plusDays(1);
                    }
                    break;
                case RANGE_MONTH:
                    // 按月分段（从startDate开始，每个月的对应日期前一天）
                    LocalDate currentMonthStart = start;
                    while (currentMonthStart.isBefore(end) || currentMonthStart.isEqual(end)) {
                        // 计算下个月的相同日期的前一天
                        LocalDate nextMonthStart = currentMonthStart.plusMonths(1);
                        LocalDate monthEnd = nextMonthStart.minusDays(1);

                        if (monthEnd.isAfter(end)) {
                            monthEnd = end;
                        }
                        long daysInMonth = ChronoUnit.DAYS.between(currentMonthStart, monthEnd) + 1;
                        dateRangeList.add(new DateRange(
                                currentMonthStart.format(formatter),
                                monthEnd.format(formatter),
                                (int) daysInMonth
                        ));
                        currentMonthStart = monthEnd.plusDays(1);
                    }
                    break;
                case RANGE_MONTH_FULL:
                    // 按月分段（每月第一天到最后一天）
                    LocalDate currentMonthFullStart = start;
                    while (currentMonthFullStart.isBefore(end) || currentMonthFullStart.isEqual(end)) {
                        LocalDate monthEnd = currentMonthFullStart.with(TemporalAdjusters.lastDayOfMonth());
                        if (monthEnd.isAfter(end)) {
                            monthEnd = end;
                        }
                        long daysInMonth = ChronoUnit.DAYS.between(currentMonthFullStart, monthEnd) + 1;
                        dateRangeList.add(new DateRange(
                                currentMonthFullStart.format(formatter),
                                monthEnd.format(formatter),
                                (int) daysInMonth
                        ));
                        currentMonthFullStart = monthEnd.plusDays(1);
                    }
                    break;
                case RANGE_SEASON:
                    // 按季分段（从startDate开始，每3个月一段）
                    LocalDate currentSeasonStart = start;
                    while (currentSeasonStart.isBefore(end) || currentSeasonStart.isEqual(end)) {
                        // 计算下季度的相同日期的前一天
                        LocalDate nextSeasonStart = currentSeasonStart.plusMonths(3);
                        LocalDate seasonEnd = nextSeasonStart.minusDays(1);

                        if (seasonEnd.isAfter(end)) {
                            seasonEnd = end;
                        }
                        long daysInSeason = ChronoUnit.DAYS.between(currentSeasonStart, seasonEnd) + 1;
                        dateRangeList.add(new DateRange(
                                currentSeasonStart.format(formatter),
                                seasonEnd.format(formatter),
                                (int) daysInSeason
                        ));
                        currentSeasonStart = seasonEnd.plusDays(1);
                    }
                    break;
                case RANGE_SEASON_FULL:
                    // 按季分段（每季度第一天到最后一天）
                    LocalDate currentSeasonFullStart = start;
                    while (currentSeasonFullStart.isBefore(end) || currentSeasonFullStart.isEqual(end)) {
                        // 计算当前季度的最后一天
                        int currentMonth = currentSeasonFullStart.getMonthValue();
                        int seasonEndMonth = ((currentMonth - 1) / 3) * 3 + 3;
                        LocalDate seasonEnd = LocalDate.of(
                                currentSeasonFullStart.getYear(),
                                seasonEndMonth,
                                currentSeasonFullStart.getMonth().length(currentSeasonFullStart.isLeapYear())
                        );

                        if (seasonEnd.isAfter(end)) {
                            seasonEnd = end;
                        }
                        long daysInSeason = ChronoUnit.DAYS.between(currentSeasonFullStart, seasonEnd) + 1;
                        dateRangeList.add(new DateRange(
                                currentSeasonFullStart.format(formatter),
                                seasonEnd.format(formatter),
                                (int) daysInSeason
                        ));
                        currentSeasonFullStart = seasonEnd.plusDays(1);
                    }
                    break;
                case RANGE_YEAR:
                    // 按年分段（从startDate开始，每年的对应日期前一天）
                    LocalDate currentYearStart = start;
                    while (currentYearStart.isBefore(end) || currentYearStart.isEqual(end)) {
                        // 计算下一年的相同日期的前一天
                        LocalDate nextYearStart = currentYearStart.plusYears(1);
                        LocalDate yearEnd = nextYearStart.minusDays(1);

                        if (yearEnd.isAfter(end)) {
                            yearEnd = end;
                        }
                        long daysInYear = ChronoUnit.DAYS.between(currentYearStart, yearEnd) + 1;
                        dateRangeList.add(new DateRange(
                                currentYearStart.format(formatter),
                                yearEnd.format(formatter),
                                (int) daysInYear
                        ));
                        currentYearStart = yearEnd.plusDays(1);
                    }
                    break;
                case RANGE_YEAR_FULL:
                    // 按年分段（每年第一天到最后一天）
                    LocalDate currentYearFullStart = start;
                    while (currentYearFullStart.isBefore(end) || currentYearFullStart.isEqual(end)) {
                        LocalDate yearEnd = LocalDate.of(
                                currentYearFullStart.getYear(),
                                12,
                                31
                        );

                        if (yearEnd.isAfter(end)) {
                            yearEnd = end;
                        }
                        long daysInYear = ChronoUnit.DAYS.between(currentYearFullStart, yearEnd) + 1;
                        dateRangeList.add(new DateRange(
                                currentYearFullStart.format(formatter),
                                yearEnd.format(formatter),
                                (int) daysInYear
                        ));
                        currentYearFullStart = yearEnd.plusDays(1);
                    }
                    break;
                default:
                    throw new IllegalArgumentException("不支持的时间单位: " + rangeType);
            }

            return dateRangeList;
        } catch (Exception e) {
            // 处理日期解析异常
            throw new IllegalArgumentException("日期解析失败: " + e.getMessage(), e);
        }
    }

    // 内部类
    public static class DateRange {
        private String startDate;
        private String endDate;
        private int daysInRange; // 新增：表示从start到end的天数

        public DateRange(String startDate, String endDate, int daysInRange) {
            this.startDate = startDate;
            this.endDate = endDate;
            this.daysInRange = daysInRange;
        }

        // Getters 和 Setters
        public String getStartDate() { return startDate; }
        public void setStartDate(String startDate) { this.startDate = startDate; }
        public String getEndDate() { return endDate; }
        public void setEndDate(String endDate) { this.endDate = endDate; }
        public int getDaysInRange() { return daysInRange; }
        public void setDaysInRange(int daysInRange) { this.daysInRange = daysInRange; }

        @Override
        public String toString() {
            return "DateRange{startDate='" + startDate + "', endDate='" + endDate + "', daysInRange=" + daysInRange + "}";
        }
    }

}
